home *** CD-ROM | disk | FTP | other *** search
/ Experimental BBS Explossion 3 / Experimental BBS Explossion III.iso / games / nhak_src.zip / TOPTEN.C < prev    next >
C/C++ Source or Header  |  1993-03-16  |  21KB  |  850 lines

  1. /*    SCCS Id: @(#)topten.c    3.0    89/12/31
  2. /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
  3. /* NetHack may be freely redistributed.  See license for details. */
  4.  
  5. #define MONATTK_H    /* comment line for pre-compiled headers */
  6. #define MONFLAG_H    /* comment line for pre-compiled headers */
  7. /* block some unused #defines to avoid overloading some cpp's */
  8. #include "hack.h"
  9.  
  10. #ifndef MACOS
  11. #include <errno.h>    /* George Barbanis */
  12. #else
  13. extern short macflags;
  14. extern WindowPtr    HackWindow;
  15. #endif
  16.  
  17. #ifdef NO_FILE_LINKS
  18. #include <fcntl.h>    /* Ralf Brown */
  19. #endif
  20. #include <ctype.h>
  21.  
  22. #ifdef NO_SCAN_BRACK
  23. static void FDECL(nsb_mung_line,(char*));
  24. static void FDECL(nsb_unmung_line,(char*));
  25. #endif
  26.  
  27. #define newttentry() (struct toptenentry *) alloc(sizeof(struct toptenentry))
  28. #define    NAMSZ    10
  29. #define    DTHSZ    60
  30. #define    PERSMAX     3        /* entries per name/uid per char. allowed */
  31. #define    POINTSMIN    1    /* must be > 0 */
  32. #define    ENTRYMAX    100    /* must be >= 10 */
  33.  
  34. #ifndef MSDOS
  35. #define    PERS_IS_UID        /* delete for PERSMAX per name; now per uid */
  36. #endif
  37. struct toptenentry {
  38.     struct toptenentry *tt_next;
  39.     long int points;
  40.     int level,maxlvl,hp,maxhp;
  41.     int uid;
  42.     char plchar;
  43.     char sex;
  44.     char name[NAMSZ+1];
  45.     char death[DTHSZ+1];
  46.     char date[7];        /* yymmdd */
  47. } *tt_head;
  48.  
  49. static char *FDECL(itoa, (int));
  50. static const char *FDECL(ordin, (int));
  51. static void NDECL(outheader);
  52. static int FDECL(outentry, (int,struct toptenentry *,int));
  53. static void FDECL(readentry, (FILE *,struct toptenentry *));
  54. static void FDECL(writeentry, (FILE *,struct toptenentry *));
  55. static int FDECL(classmon, (CHAR_P,BOOLEAN_P));
  56. static boolean FDECL(onlyspace, (const char *));
  57.  
  58. /* must fit with end.c */
  59. static const char NEARDATA *killed_by_prefix[] = {
  60.     "killed by ", "choked on ", "poisoned by ", "", "drowned in ",
  61.     "", "crushed to death by ", "petrified by ", "",
  62.     "", "",
  63.     "", "", "" };
  64.  
  65. static void
  66. readentry(rfile,tt)
  67. FILE *rfile;
  68. struct toptenentry *tt;
  69. {
  70. # ifdef NO_SCAN_BRACK
  71.     if(fscanf(rfile,"%6s %d %d %d %d %d %ld%*c%c%c %s %s",
  72. #  define TTFIELDS 12
  73. # else
  74.     if(fscanf(rfile, "%6s %d %d %d %d %d %ld %c%c %[^,],%[^\n]",
  75. #  define TTFIELDS 11
  76. # endif
  77.         tt->date, &tt->uid,
  78.         &tt->level,
  79.         &tt->maxlvl, &tt->hp, &tt->maxhp, &tt->points,
  80.         &tt->plchar, &tt->sex,
  81. #ifdef LATTICE    /* return value is broken also, sigh */
  82.         tt->name, tt->death) < 1)
  83. #else
  84.         tt->name, tt->death) != TTFIELDS)
  85. #endif
  86. #undef TTFIELDS
  87.             tt->points = 0;
  88. #ifdef NO_SCAN_BRACK
  89.     if(tt->points > 0) {
  90.         nsb_unmung_line(tt->name);
  91.         nsb_unmung_line(tt->death);
  92.     }
  93. #endif
  94. }
  95.  
  96. static void
  97. writeentry(rfile,tt)
  98. FILE *rfile;
  99. struct toptenentry *tt;
  100. {
  101. #ifdef NO_SCAN_BRACK
  102.     nsb_mung_line(tt->name);
  103.     nsb_mung_line(tt->death);
  104. #endif
  105. # ifdef NO_SCAN_BRACK
  106.     (void) fprintf(rfile,"%6s %d %d %d %d %d %ld %c%c %s %s\n",
  107. # else
  108.     (void) fprintf(rfile,"%6s %d %d %d %d %d %ld %c%c %s,%s\n",
  109. # endif
  110.         tt->date, tt->uid,
  111.         tt->level,
  112.         tt->maxlvl, tt->hp, tt->maxhp, tt->points,
  113.         tt->plchar, tt->sex,
  114.         onlyspace(tt->name) ? "_" : tt->name, tt->death);
  115. #ifdef NO_SCAN_BRACK
  116.     nsb_unmung_line(tt->name);
  117.     nsb_unmung_line(tt->death);
  118. #endif
  119. }
  120.  
  121. static boolean
  122. onlyspace(s)
  123. const char *s;
  124. {
  125.     for (;*s;s++) if (!isspace(*s)) return(FALSE);
  126.     return(TRUE);
  127. }
  128.  
  129. void
  130. topten(how)
  131. int how;
  132. {
  133.     int uid = getuid();
  134.     int rank, rank0 = -1, rank1 = 0;
  135.     int occ_cnt = PERSMAX;
  136.     register struct toptenentry *t0, *tprev;
  137.     register struct toptenentry *t1;
  138. #ifdef UNIX
  139.     char *reclock = "record_lock";
  140. # ifdef NO_FILE_LINKS
  141.     int lockfd ;
  142. # endif
  143. #endif /* UNIX */
  144. #ifdef VMS
  145.     char *reclock = "record_lock;1";
  146.     char recfile[] = RECORD;
  147. #else
  148.     const char *recfile = RECORD;
  149. #endif
  150. #if defined(UNIX) || defined(VMS)
  151.     int sleepct = 100;
  152. #endif
  153.     FILE *rfile;
  154.     register int flg = 0;
  155. #ifdef LOGFILE
  156.     char *lgfile = LOGFILE;
  157.     FILE *lfile;
  158. # ifdef UNIX
  159.     char *loglock = "logfile_lock";
  160. # endif /* UNIX */
  161. # ifdef VMS
  162.     char *loglock = "logfile_lock;1";
  163. # endif /* VMS */
  164. # if defined(UNIX) || defined(VMS)
  165.     int sleeplgct = 30;
  166. # endif /* UNIX or VMS */
  167. #endif /* LOGFILE */
  168.  
  169. #if defined(MSDOS) || defined(MACOS)
  170. #define HUP
  171. #else
  172. #define    HUP    if(!done_hup)
  173. #endif
  174. #ifdef MACOS
  175.     macflags &= ~fDoUpdate;
  176.     uid = TickCount();
  177. #endif
  178.     /* create a new 'topten' entry */
  179.     t0 = newttentry();
  180.     t0->level = dlevel;
  181.     t0->maxlvl = maxdlevel;
  182.     t0->hp = u.uhp;
  183.     t0->maxhp = u.uhpmax;
  184.     t0->points = u.urexp;
  185.     t0->plchar = pl_character[0];
  186.     t0->sex = (flags.female ? 'F' : 'M');
  187.     t0->uid = uid;
  188.     (void) strncpy(t0->name, plname, NAMSZ);
  189.     (t0->name)[NAMSZ] = 0;
  190.     (t0->death)[0] = 0;
  191.     switch (killer_format) {
  192.         default: impossible("bad killer format?");
  193.         case KILLED_BY_AN:
  194.             Strcat(t0->death, killed_by_prefix[how]),
  195.             (void) strncat(t0->death, an(killer), DTHSZ);
  196.             break;
  197.         case KILLED_BY:
  198.             Strcat(t0->death, killed_by_prefix[how]),
  199.             (void) strncat(t0->death, killer, DTHSZ);
  200.             break;
  201.         case NO_KILLER_PREFIX:
  202.             (void) strncat(t0->death, killer, DTHSZ);
  203.             break;
  204.     }
  205.     Strcpy(t0->date, getdate());
  206.  
  207. #ifdef LOGFILE        /* used for debugging (who dies of what, where) */
  208. # if defined(UNIX) || defined(VMS)
  209. #  ifdef NO_FILE_LINKS
  210.     loglock = (char *)alloc(sizeof(LOCKDIR)+1+strlen(lgfile)+6);
  211.     Strcpy(loglock,LOCKDIR) ;
  212.     Strcat(loglock,"/") ;
  213.     Strcat(loglock,lgfile) ;
  214.     Strcat(loglock,"_lock") ;
  215.     while ((lockfd = open(loglock,O_RDWR|O_CREAT|O_EXCL,0666)) == -1) {
  216. #  else
  217.     while(link(lgfile, loglock) == -1) {
  218. #  endif /* NO_FILE_LINKS */
  219.         extern int errno;
  220.  
  221.         if (errno == ENOENT) /* If no such file, do not keep log */
  222.             goto lgend;  /* George Barbanis */
  223.         HUP perror(loglock);
  224.         if(!sleeplgct--) {
  225.             HUP (void) puts("I give up.  Sorry.");
  226.             HUP (void) puts("Perhaps there is an old logfile_lock around?");
  227.             goto lgend;
  228.         }
  229.         HUP Printf("Waiting for access to log file. (%d)\n",
  230.              sleeplgct);
  231.         HUP (void) fflush(stdout);
  232. #  if defined(SYSV) || defined(ULTRIX) || defined(VMS)
  233.         (void)
  234. #  endif
  235.             sleep(1);
  236.     }
  237. # endif /* UNIX or VMS */
  238.     if(!(lfile = fopen(lgfile,"a"))){
  239.         HUP (void) puts("Cannot open log file!");
  240.         goto lgend;
  241.     }
  242.     writeentry(lfile, t0);
  243.     (void) fclose(lfile);
  244. # if defined(UNIX) || defined(VMS)
  245.     (void) unlink(loglock);
  246. # endif /* UNIX or VMS */
  247.       lgend:;
  248. # ifdef NO_FILE_LINKS
  249.     (void) close(lockfd) ;
  250. # endif
  251. # if defined(WIZARD) || defined(EXPLORE_MODE)
  252.     if (wizard || discover) {
  253.  Printf("\nSince you were in %s mode, the score list will not be checked.\n",
  254.     wizard ? "wizard" : "discover");
  255.         return;
  256.     }
  257. # endif
  258. #endif /* LOGFILE */
  259.  
  260. #if defined(UNIX) || defined(VMS)
  261. # ifdef NO_FILE_LINKS
  262.     reclock = (char *)alloc(sizeof(LOCKDIR)+1+strlen(recfile)+7);
  263.     Strcpy(reclock,LOCKDIR) ;
  264.     Strcat(reclock,"/") ;
  265.     Strcat(reclock,recfile) ;
  266.     Strcat(reclock,"_lock") ;
  267.     while ((lockfd = open(reclock,O_RDWR|O_CREAT|O_EXCL,0666)) == -1) {
  268. # else
  269.     while(link(recfile, reclock) == -1) {
  270. # endif /* NO_FILE_LINKS */
  271.         HUP perror(reclock);
  272.         if(!sleepct--) {
  273.             HUP (void) puts("I give up.  Sorry.");
  274.             HUP (void) puts("Perhaps there is an old record_lock around?");
  275.             return;
  276.         }
  277.         HUP Printf("Waiting for access to record file. (%d)\n",
  278.             sleepct);
  279.         HUP (void) fflush(stdout);
  280. # if defined(SYSV) || defined(ULTRIX) || defined(VMS)
  281.         (void)
  282. # endif
  283.             sleep(1);
  284.     }
  285. #endif /* UNIX or VMS */
  286. #ifdef MACOS
  287.     {
  288.         term_info    *t;
  289.         
  290.         t = (term_info *)GetWRefCon(HackWindow);
  291.         SetVol((StringPtr)0L, t->recordVRefNum);
  292.         if (!(rfile = fopen(recfile,"r"))) {
  293.             short    i;
  294.     
  295.             rfile = openFile(recfile,"r");
  296.         }
  297.     }
  298.  
  299.     if (!rfile) {
  300. #else
  301.     if(!(rfile = fopen(recfile,"r"))){
  302. #endif
  303.         HUP (void) puts("Cannot open record file!");
  304.         goto unlock;
  305.     }
  306. #ifdef NO_FILE_LINKS
  307.     (void) close(lockfd) ;
  308. #endif
  309.     HUP (void) putchar('\n');
  310.  
  311.     /* assure minimum number of points */
  312.     if(t0->points < POINTSMIN) t0->points = 0;
  313.  
  314.     t1 = tt_head = newttentry();
  315.     tprev = 0;
  316.     /* rank0: -1 undefined, 0 not_on_list, n n_th on list */
  317.     for(rank = 1; ; ) {
  318.         readentry(rfile, t1);
  319.         if (t1->points < POINTSMIN) t1->points = 0;
  320.         if(rank0 < 0 && t1->points < t0->points) {
  321.         rank0 = rank++;
  322.         if(tprev == 0)
  323.             tt_head = t0;
  324.         else
  325.             tprev->tt_next = t0;
  326.         t0->tt_next = t1;
  327.         occ_cnt--;
  328.         flg++;        /* ask for a rewrite */
  329.         } else tprev = t1;
  330.  
  331.         if(t1->points == 0) break;
  332.         if(
  333. #ifdef PERS_IS_UID
  334.         t1->uid == t0->uid &&
  335. #else
  336.         strncmp(t1->name, t0->name, NAMSZ) == 0 &&
  337. #endif
  338.         t1->plchar == t0->plchar && --occ_cnt <= 0) {
  339.             if(rank0 < 0) {
  340.             rank0 = 0;
  341.             rank1 = rank;
  342.     HUP Printf("You didn't beat your previous score of %ld points.\n\n",
  343.                 t1->points);
  344.             }
  345.             if(occ_cnt < 0) {
  346.             flg++;
  347.             continue;
  348.             }
  349.         }
  350.         if(rank <= ENTRYMAX) {
  351.         t1 = t1->tt_next = newttentry();
  352.         rank++;
  353.         }
  354.         if(rank > ENTRYMAX) {
  355.         t1->points = 0;
  356.         break;
  357.         }
  358.     }
  359.     if(flg) {    /* rewrite record file */
  360.         (void) fclose(rfile);
  361. #ifdef VMS
  362.         {
  363.             char *sem = rindex(recfile, ';');
  364.  
  365.             if (sem)
  366.                 *sem = '\0';
  367.         }
  368. #endif
  369.         if(!(rfile = fopen(recfile,"w"))){
  370.             HUP (void) puts("Cannot write record file\n");
  371.             goto unlock;
  372.         }
  373.  
  374.         if(!done_stopprint) if(rank0 > 0){
  375.             if(rank0 <= 10)
  376.             (void) puts("You made the top ten list!\n");
  377.             else
  378.         Printf("You reached the %d%s place on the top %d list.\n\n",
  379.             rank0, ordin(rank0), ENTRYMAX);
  380.         }
  381.     }
  382.     if(rank0 == 0) rank0 = rank1;
  383.     if(rank0 <= 0) rank0 = rank;
  384.     if(!done_stopprint) outheader();
  385.     t1 = tt_head;
  386.     for(rank = 1; t1->points != 0; rank++, t1 = t1->tt_next) {
  387.         if(flg) writeentry(rfile, t1);
  388.         if(done_stopprint) continue;
  389.         if(rank > flags.end_top &&
  390.           (rank < rank0-flags.end_around || rank > rank0+flags.end_around)
  391.           && (!flags.end_own ||
  392. #ifdef PERS_IS_UID
  393.                   t1->uid != t0->uid
  394. #else
  395.                   strncmp(t1->name, t0->name, NAMSZ)
  396. #endif
  397.         )) continue;
  398.         if(rank == rank0-flags.end_around &&
  399.            rank0 > flags.end_top+flags.end_around+1 &&
  400.            !flags.end_own)
  401.         (void) putchar('\n');
  402.         if(rank != rank0)
  403.         (void) outentry(rank, t1, 0);
  404.         else if(!rank1)
  405.         (void) outentry(rank, t1, 1);
  406.         else {
  407.         int t0lth = outentry(0, t0, -1);
  408.         int t1lth = outentry(rank, t1, t0lth);
  409.         if(t1lth > t0lth) t0lth = t1lth;
  410.         (void) outentry(0, t0, t0lth);
  411.         }
  412.     }
  413.     if(rank0 >= rank) if(!done_stopprint)
  414.         (void) outentry(0, t0, 1);
  415.     (void) fclose(rfile);
  416. #ifdef MACOS
  417.     {
  418.         Str255    name;
  419.         FInfo    fndrInfo;
  420.         term_info    *t;
  421.         short    oldVol, error;
  422.         
  423.         t = (term_info *)GetWRefCon(HackWindow);
  424.         GetVol(name, &oldVol);
  425.         SetVol(0L, t->recordVRefNum);
  426.         Strcpy((char *)name,recfile);
  427.         CtoPstr((char *)name);
  428.         error = GetFInfo(name, (short)0, &fndrInfo);
  429.         fndrInfo.fdCreator = CREATOR;
  430.         if (error == noErr)
  431.             SetFInfo(name, (short)0, &fndrInfo);
  432.         SetVol(0L, oldVol);
  433.     }
  434. #endif
  435. #ifdef VMS
  436.     if (flg) {
  437.         delete(RECORD);
  438.         rename(recfile, RECORD);
  439.     }
  440. # undef unlink
  441. #endif
  442. unlock:    ;
  443. #if defined(UNIX) || defined(VMS)
  444. # ifdef NO_FILE_LINKS
  445.     (void) close(lockfd) ;
  446. # endif
  447.     if (unlink(reclock) < 0)
  448.         Printf("Can't unlink %s\n",reclock) ;
  449. #endif
  450. }
  451.  
  452. static void
  453. outheader() {
  454.     char linebuf[BUFSZ];
  455.     register char *bp;
  456.  
  457.     Strcpy(linebuf, " No  Points     Name");
  458.     bp = eos(linebuf);
  459.     while(bp < linebuf + COLNO - 9) *bp++ = ' ';
  460.     Strcpy(bp, "Hp [max]");
  461.     (void) puts(linebuf);
  462. #ifdef MACOS
  463.     putchar('\n');
  464. #endif
  465. }
  466.  
  467. /* so>0: standout line; so=0: ordinary line; so<0: no output, return lth */
  468. static int
  469. outentry(rank, t1, so)
  470. register struct toptenentry *t1;
  471. register int rank, so;
  472. {
  473.     register boolean second_line = TRUE;
  474.     char linebuf[BUFSZ], linebuf2[BUFSZ];
  475.  
  476.     linebuf[0] = linebuf2[0] = 0;
  477.     if(rank) Sprintf(eos(linebuf), " %2d", rank);
  478.     else Strcat(linebuf, "   ");
  479.  
  480.     Sprintf(eos(linebuf), " %10ld  %.10s", t1->points, t1->name);
  481.     Sprintf(eos(linebuf), "-%c ", t1->plchar);
  482.     if(!strncmp("escaped", t1->death, 7)) {
  483.       second_line = FALSE;
  484.       if(!strcmp(" (with the Amulet)", t1->death+7))
  485.         Strcat(linebuf, "escaped the dungeon with the Amulet");
  486.       else
  487.         Sprintf(eos(linebuf), "escaped the dungeon [max level %d]",
  488.           t1->maxlvl);
  489. #ifdef ENDGAME
  490.     } else if(!strncmp("ascended", t1->death, 8)) {
  491.        Strcat(linebuf, "ascended to demigod");
  492.        if (t1->sex == 'F') Strcat(linebuf, "dess");
  493.        Strcat(linebuf, "-hood");
  494.        second_line = FALSE;
  495. #endif
  496.     } else {
  497.       if(!strncmp(t1->death,"quit",4)) {
  498.         Strcat(linebuf, "quit");
  499.         second_line = FALSE;
  500.       } else if(!strncmp(t1->death,"starv",5)) {
  501.         Strcat(linebuf, "starved to death");
  502.         second_line = FALSE;
  503.       } else if(!strncmp(t1->death,"choked",6)) {
  504.         Sprintf(eos(linebuf), "choked on h%s food",
  505.             (t1->sex == 'F') ? "er" : "is");
  506.       } else if(!strncmp(t1->death,"poisoned",8)) {
  507.         Strcat(linebuf, "was poisoned");
  508.       } else if(!strncmp(t1->death,"crushed",7)) {
  509.         Strcat(linebuf, "was crushed to death");
  510.       } else if(!strncmp(t1->death, "petrified by ",13)) {
  511.         Strcat(linebuf, "turned to stone");
  512.       } else Strcat(linebuf, "died");
  513. #ifdef ENDLEVEL
  514.       if (t1->level == ENDLEVEL)
  515.         Strcat(linebuf, " in the endgame");
  516.       else
  517. #endif
  518.         Sprintf(eos(linebuf), " on dungeon level %d", t1->level);
  519.       if(t1->maxlvl != t1->level)
  520.         Sprintf(eos(linebuf), " [max %d]", t1->maxlvl);
  521.     /* kludge for "quit while already on Charon's boat" */
  522.       if(!strncmp(t1->death, "quit ", 5))
  523.         Strcat(linebuf, t1->death + 4);
  524.     }
  525.     Strcat(linebuf, ".");
  526.  
  527.     if(t1->maxhp) {
  528.       register char *bp = eos(linebuf);
  529.       char hpbuf[10];
  530.       int hppos;
  531.       int lngr = strlen(linebuf);
  532.       Strcpy(hpbuf, (t1->hp > 0) ? itoa(t1->hp) : "-");
  533.       hppos = COLNO - 7 - strlen(hpbuf);
  534.       if (lngr >= hppos) hppos = (2*COLNO) - 7 - strlen(hpbuf);
  535.       if(bp <= linebuf + hppos) {
  536.         /* pad any necessary blanks to the hit point entry */
  537. #ifdef MACOS
  538.         while(bp <= linebuf + hppos) *bp++ = ' ';
  539. #else
  540.         while(bp < linebuf + hppos) *bp++ = ' ';
  541. #endif
  542.         Strcpy(bp, hpbuf);
  543.         if(t1->maxhp < 10)
  544.          Sprintf(eos(bp), "   [%d]", t1->maxhp);
  545.         else if(t1->maxhp < 100)
  546.          Sprintf(eos(bp), "  [%d]", t1->maxhp);
  547.         else Sprintf(eos(bp), " [%d]", t1->maxhp);
  548.       }
  549.     }
  550.  
  551. /*    Line 2 now contains the killer name */
  552.  
  553.     /* Quit, starved, ascended, and escaped contain no second line */
  554.     if (second_line) {
  555.         Strcpy(linebuf2, t1->death);
  556.         if (islower(*linebuf2)) *linebuf2 = toupper(*linebuf2);
  557.         Strcat(linebuf2, ".");
  558.     }
  559.  
  560.     if(so == 0) {
  561.       (void) puts(linebuf);
  562.       if (second_line)
  563.         (void) Printf("                %s\n", linebuf2);
  564.     } else if(so > 0) {
  565.       register char *bp = eos(linebuf);
  566.       if(so >= COLNO) so = COLNO-1;
  567.       while(bp < linebuf + so) *bp++ = ' ';
  568.       *bp = 0;
  569.       standoutbeg();
  570.       (void) puts(linebuf);
  571.       if(second_line)
  572.         (void) Printf("                %s", linebuf2);
  573.       standoutend();
  574.       if(second_line)
  575.         (void) putchar('\n');
  576.     }
  577.     return(strlen(linebuf)+strlen(linebuf2));
  578. }
  579.  
  580. static char *
  581. itoa(a) int a; {
  582. #ifdef LINT    /* static char buf[12]; */
  583. char buf[12];
  584. #else
  585. static char buf[12];
  586. #endif
  587.     Sprintf(buf,"%d",a);
  588.     return(buf);
  589. }
  590.  
  591. static const char *
  592. ordin(n)
  593. int n; {
  594.     register int dd = n%10;
  595.  
  596. #if ENTRYMAX > 110
  597.     return((dd==0 || dd>3 || (n/10)%10==1) ? "th" :
  598. #else
  599.     return((dd==0 || dd>3 || n/10==1) ? "th" :
  600. #endif
  601.            (dd==1) ? "st" : (dd==2) ? "nd" : "rd");
  602. }
  603.  
  604. /*
  605.  * Called with args from main if argc >= 0. In this case, list scores as
  606.  * requested. Otherwise, find scores for the current player (and list them
  607.  * if argc == -1).
  608.  */
  609. void
  610. prscore(argc,argv)
  611. int argc;
  612. char **argv;
  613. {
  614.     const char **players;
  615.     int playerct;
  616.     int rank;
  617.     register struct toptenentry *t1, *t2;
  618.     const char *recfile = RECORD;
  619.     FILE *rfile;
  620.     register int flg = 0, i;
  621. #ifdef nonsense
  622.     long total_score = 0L;
  623.     char totchars[10];
  624.     int totcharct = 0;
  625. #endif
  626.     int outflg = (argc >= -1);
  627. #ifdef PERS_IS_UID
  628.     int uid = -1;
  629. #else
  630.     const char *player0;
  631. #endif
  632. #ifdef MACOS
  633.     if(!(rfile = fopen(recfile,"r")))
  634.         rfile = openFile(recfile,"r");
  635.     if (!rfile) {
  636. #else
  637.     if(!(rfile = fopen(recfile,"r"))){
  638. #endif
  639.         (void) puts("Cannot open record file!");
  640.         return;
  641.     }
  642.  
  643.     if(argc > 1 && !strncmp(argv[1], "-s", 2)){
  644.         if(!argv[1][2]){
  645.             argc--;
  646.             argv++;
  647.         } else if(!argv[1][3] && index(pl_classes, argv[1][2])) {
  648.             argv[1]++;
  649.             argv[1][0] = '-';
  650.         } else    argv[1] += 2;
  651.     }
  652.     if(argc <= 1){
  653. #ifdef PERS_IS_UID
  654.         uid = getuid();
  655.         playerct = 0;
  656. #else
  657.         player0 = plname;
  658.         if(!*player0)
  659.             player0 = "hackplayer";
  660.         playerct = 1;
  661.         players = &player0;
  662. #endif
  663.     } else {
  664.         playerct = --argc;
  665.         players = (const char **)++argv;
  666.     }
  667.     if(outflg) (void) putchar('\n');
  668.  
  669.     t1 = tt_head = newttentry();
  670.     for(rank = 1; ; rank++) {
  671.         readentry(rfile, t1);
  672.         if(t1->points == 0) break;
  673. #ifdef PERS_IS_UID
  674.         if(!playerct && t1->uid == uid)
  675.         flg++;
  676.         else
  677. #endif
  678.         for(i = 0; i < playerct; i++){
  679.         if(strcmp(players[i], "all") == 0 ||
  680.            strncmp(t1->name, players[i], NAMSZ) == 0 ||
  681.           (players[i][0] == '-' &&
  682.            players[i][1] == t1->plchar &&
  683.            players[i][2] == 0) ||
  684.           (digit(players[i][0]) && rank <= atoi(players[i])))
  685.             flg++;
  686.         }
  687.         t1 = t1->tt_next = newttentry();
  688.     }
  689.     (void) fclose(rfile);
  690.     if(!flg) {
  691.         if(outflg) {
  692.         Printf("Cannot find any entries for ");
  693.         if(playerct < 1) Printf("you.\n");
  694.         else {
  695.           if(playerct > 1) Printf("any of ");
  696.           for(i=0; i<playerct; i++)
  697.             Printf("%s%s", players[i], (i<playerct-1)?", ":".\n");
  698.           Printf("Call is: %s -s [-role] [maxrank] [playernames]\n", hname);
  699.         }
  700.         }
  701.         return;
  702.     }
  703.  
  704.     if(outflg) outheader();
  705.     t1 = tt_head;
  706.     for(rank = 1; t1->points != 0; rank++, t1 = t2) {
  707.         t2 = t1->tt_next;
  708. #ifdef PERS_IS_UID
  709.         if(!playerct && t1->uid == uid)
  710.             goto outwithit;
  711.         else
  712. #endif
  713.         for(i = 0; i < playerct; i++){
  714.             if(strcmp(players[i], "all") == 0 ||
  715.                strncmp(t1->name, players[i], NAMSZ) == 0 ||
  716.               (players[i][0] == '-' &&
  717.                players[i][1] == t1->plchar &&
  718.                players[i][2] == 0) ||
  719.               (digit(players[i][0]) && rank <= atoi(players[i]))){
  720. #ifdef PERS_IS_UID
  721.             outwithit:
  722. #endif
  723.                 if(outflg)
  724.                     (void) outentry(rank, t1, 0);
  725. #ifdef nonsense
  726.                 total_score += t1->points;
  727.                 if(totcharct < sizeof(totchars)-1)
  728.                     totchars[totcharct++] = t1->plchar;
  729. #endif
  730.                 break;
  731.             }
  732.         }
  733.         free((genericptr_t) t1);
  734.     }
  735. #ifdef nonsense
  736.     totchars[totcharct] = 0;
  737.  
  738.     /* We would like to determine whether he is experienced. However,
  739.        the information collected here only tells about the scores/roles
  740.        that got into the topten (top 100?). We should maintain a
  741.        .hacklog or something in his home directory. */
  742.     flags.beginner = (total_score < 6000);
  743.     for(i=0; i<6; i++)
  744.         if(!index(totchars, pl_classes[i])) {
  745.         flags.beginner = 1;
  746.         if(!pl_character[0]) pl_character[0] = pl_classes[i];
  747.         break;
  748.     }
  749. #endif /* nonsense /**/
  750. #ifdef MACOS
  751.     more();
  752. #endif
  753. }
  754.  
  755. static int
  756. classmon(plch, fem)
  757. char plch;
  758. boolean fem;
  759. {
  760.     switch (plch) {
  761.         case 'A': return PM_ARCHEOLOGIST;
  762.         case 'B': return PM_BARBARIAN;
  763.         case 'C': return (fem ? PM_CAVEWOMAN : PM_CAVEMAN);
  764.         case 'E': return PM_ELF;
  765.         case 'H': return PM_HEALER;
  766.         case 'F':    /* accept old Fighter class */
  767.         case 'K': return PM_KNIGHT;
  768.         case 'P': return (fem ? PM_PRIESTESS : PM_PRIEST);
  769.         case 'R': return PM_ROGUE;
  770.         case 'N':    /* accept old Ninja class */
  771.         case 'S': return PM_SAMURAI;
  772.         case 'T': return PM_TOURIST;
  773.         case 'V': return PM_VALKYRIE;
  774.         case 'W': return PM_WIZARD;
  775.         default: impossible("What weird class is this? (%c)", plch);
  776.             return PM_HUMAN_ZOMBIE;
  777.     }
  778. }
  779.  
  780. /*
  781.  * Get a random player name and class from the high score list,
  782.  * and attach them to an object (for statues or morgue corpses).
  783.  */
  784. struct obj *
  785. tt_oname(otmp)
  786. struct obj *otmp;
  787. {
  788.     int rank;
  789.     register int i;
  790.     register struct toptenentry *tt;
  791.     const char *recfile = RECORD;
  792.     FILE *rfile;
  793.  
  794.     if (!otmp) return((struct obj *) 0);
  795.  
  796. #ifdef MACOS
  797.     if(!(rfile = fopen(recfile,"r")))
  798.         rfile = openFile(recfile, "r");
  799.     if (!rfile) {
  800. #else
  801.     if(!(rfile = fopen(recfile,"r"))){
  802. #endif
  803.         panic("Cannot open record file!");
  804.     }
  805.  
  806.     tt = newttentry();
  807.     rank = rnd(10);
  808. pickentry:
  809.     for(i = rank; i; i--) {
  810.         readentry(rfile, tt);
  811.         if(tt->points == 0) break;
  812.     }
  813.  
  814.     if(tt->points == 0) {
  815.         if(rank > 1) {
  816.             rank = 1;
  817.             goto pickentry;
  818.         }
  819.         free((genericptr_t) tt);
  820.         otmp = (struct obj *) 0;
  821.     } else {
  822.         otmp->corpsenm = classmon(tt->plchar, (tt->sex == 'F'));
  823.         otmp->owt = weight(otmp);
  824.         /* Note: oname() is safe since otmp is first in chains */
  825.         otmp = oname(otmp, tt->name, 0);
  826.         fobj = otmp;
  827.         level.objects[otmp->ox][otmp->oy] = otmp;
  828.         free((genericptr_t) tt);
  829.     }
  830.  
  831.     (void) fclose(rfile);
  832.     return otmp;
  833. }
  834.  
  835. #ifdef NO_SCAN_BRACK
  836. /* Lattice scanf isn't up to reading the scorefile.  What */
  837. /* follows deals with that; I admit it's ugly. (KL) */
  838. /* Now generally available (KL) */
  839. static void nsb_mung_line(p)
  840.     char *p;
  841.     {
  842.     while(p=strchr(p,' '))*p='|';
  843. }
  844. static void nsb_unmung_line(p)
  845.     char *p;
  846.     {
  847.     while(p=strchr(p,'|'))*p=' ';
  848. }
  849. #endif
  850.